package com.Book.test_1_25_springmvcbook.config;

import com.Book.test_1_25_springmvcbook.model.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice // 这是一个控制器
public class ResponseAdvice implements ResponseBodyAdvice {
    // 这里面做统一结果返回

    //统⼀的数据返回格式使⽤ @ControllerAdvice 和 ResponseBodyAdvice 的⽅式实现
    //@ControllerAdvice 表⽰控制器通知类
    //添加类 ResponseAdvice , 实现 ResponseBodyAdvice 接⼝, 并在类上添加
    //@ControllerAdvice 注解

    @Autowired
    private ObjectMapper objectMapper; // 为了 封装 String 类型的 body 需要注入这个 对象 定义一个 jackson 的对象
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true; // 要把他改成 true  表示生效

        // supports⽅法: 判断是否要执⾏beforeBodyWrite⽅法. true为执⾏, false不执⾏. 通过该⽅法可以
        //选择哪些类或哪些⽅法的response要进⾏处理, 其他的不进⾏处理
    }

    @SneakyThrows // 这个注解也是Lombok里面的一个, 会帮我们生成一个 try catch
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
       // • beforeBodyWrite⽅法: 对response⽅法进⾏具体操作处理

        // 在返回之前需要做的事情
        // Controller 方法 的接口在返回之前需要做的事情

        // body 是返回的一个结果
//        return Result.success(body);

        // 经过测试发现, 还是会有一些问题
        // 问题一: 请求返回类型为 Result 时 就不需要再进行处理了, 本身已经是封装好的了
        // 问题二: 当返回结构为String 时, 不能正确进行处理

        // 接下来进行处理

        if(body instanceof Result){
            return body;
        }
        if(body instanceof String){
            // 这里需要对 body 进行一个封装
            return objectMapper.writeValueAsString(Result.success(body));
        }
        return Result.success(body);
    }

    // 接下来解释 为什么
    /// 为什么 在 返回 String 类型的时候会出错呢?
    //  而其他的类型没有报错
    // 这是从 源码的部分说起
    // SpringMVC默认会注册⼀些⾃带的 HttpMessageConverter (这是个转换器) (从先后顺序排列分别为
    //ByteArrayHttpMessageConverter ,
    //StringHttpMessageConverter , SourceHttpMessageConverter ,
    //SourceHttpMessageConverter , AllEncompassingFormHttpMessageConverter )
}
